package com.liang.common.components;

import com.liang.entity.CUser;
import com.liang.service.CUserService;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @name: JwtAuthorizationTokenFilter
 * @author: 李昂
 * @date: 2020-12-01 13:07
 * @description：JwtAuthorizationTokenFilter
 * @update: 2020-12-01 13:07
 */
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private CUserService userService;

    @Value("${jwt.token}")
    private String tokenHeader;

    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        final String requestHeader = request.getHeader(this.tokenHeader);  // 从header 中获取token

        String username = null;
        String authToken = null;

        // token 以 Bearer 为前缀，表示 Bearer Token ，区别于MAC Token
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            authToken = requestHeader.substring(7);
            try {
                // 从token中解析出 username
                username = jwtTokenUtil.getUsernameFromToken(authToken);
            } catch (ExpiredJwtException e) {
            }
        }

        // 验证token
        if (username != null && jwtTokenUtil.validateToken(authToken, username)) {
            // 查询UserDetails
            UserDetails userDetails = this.loadUserByUsername(username);
            // 在上下文中记录UserDetails，考虑到服务器的压力  这里的信息保存的要尽可能少
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        chain.doFilter(request, response);
    }

    public UserDetails loadUserByUsername(String username) throws Exception {

        List<GrantedAuthority> authorityList = new ArrayList<>();
        /* 此处查询数据库得到角色权限列表，这里可以用Redis缓存以增加查询速度 */
        // 角色 需要以 ROLE_ 开头
        CUser user = userService.getUserBySno(username);
        String[] roles = user.getRole().split(",");
        for (String role : roles) {
            authorityList.add(new SimpleGrantedAuthority("ROLE_" + role));
        }
        return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true,
                true, true, authorityList);
    }
}